<template>
  <div class="select-tree-comp">
    <el-input
      v-bind="$attrs"
      v-model="currentName"
      @click.native="handleInputClick"
      @focus="handleFocus"
      @input="handleInput"
      @blur="handleBlur">
    </el-input>
    <el-tree
      v-show="hasShow"
      class="menu-filter-tree"
      ref="tree"
      highlight-current
      :current-node-key="currentKey"
      :data="menus"
      :props="defaultProps"
      node-key="id"
      default-expand-all
      @node-click="handleClick"
      :filter-node-method="filterNode">
    </el-tree>
  </div>
</template>

<script>
export default {
  model: {
    prop: 'value',
    event: 'change'
  },
  props: {
    value: {
      type: String,
      default: ''
    },
    defaultProps: {
      type: Object,
      default: () => ({
        children: 'children',
        label: 'name'
      })
    },
    getData: {
      type: Function,
      default: () => () => {}
    },
    menus: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      eleDom: null,
      hasFocus: false,
      currentKey: '',
      currentName: '',
      activeData: {},
      hasShow: false
    };
  },
  computed: {
    labelKey() {
      return this.defaultProps.label || 'name';
    }
  },
  watch: {
    value: {
      immediate: true,
      handler: function(id) {
        this.currentKey = id;
        this.$nextTick(() => {
          const { data } = this.$refs.tree.getNode(id) || {};
          if (data) {
            this.currentName = data[this.labelKey];
            this.activeData = data || {};
          }
        });
      }
    },
    menus(val) {
      if (Array.isArray(val) && !this.currentName) {
        this.$nextTick(() => {
          const { data } = this.$refs.tree.getNode(this.currentKey) || {};
          if (data) {
            this.currentName = data[this.labelKey];
            this.activeData = data || {};
          }
        });
      }
    }
  },
  mounted() {
    this.eleDom = document.querySelector('.select-tree-comp');
  },
  methods: {
    // 点击菜单节点
    handleClick(data, node, ref) {
      const { id } = data;
      this.currentKey = id;
      this.activeData = data;
      this.currentName = data[this.labelKey];
      this.hasShow = false;
      this.hasFocus = false;
      this.$emit('change', id);
      this.getData && this.getData({ ...data });
    },
    handleInputClick() {
      if (this.hasFocus) return;
      this.hasShow = !this.hasShow;
    },
    handleInput(val) {
      this.$refs.tree && this.$refs.tree.filter(val);
    },
    handleFocus() {
      this.hasFocus = true;
      setTimeout(() => {
        this.hasFocus = false;
      }, 300);
      this.hasShow = true;
    },
    handleBlur(e) {
      this.hasFocus = false;
      // const elDom = this.eleDom || document.querySelector('.select-tree-comp');
      // this.hasShow = e.relatedTarget && elDom.contains(e.relatedTarget);
      const className = e.relatedTarget && e.relatedTarget.className;
      this.hasShow = className && /el-tree/g.test(className);
      if (this.currentName !== this.activeData[this.labelKey]) {
        this.currentName = this.activeData[this.labelKey] || '';
        this.handleInput('');
      }
    },
    // 过滤节点
    filterNode(value, data) {
      if (!value) return true;
      return data[this.labelKey].indexOf(value) !== -1;
    },
  }
};
</script>

<style scoped lang="scss">
  .select-tree-comp {
    width: 100%;
    position: relative;
    .menu-filter-tree {
      position: absolute;
      top: 38px;
      left: 1px;
      width: 100%;
      max-height: 300px;
      z-index: 2;
      background-color: #fff;
      border: 1px solid #f1f1f1;
      border-top-color: transparent;
      box-shadow: 0 2px 8px 0 #bbb;
      border-radius: 4px;
      overflow-y: auto;
    }
  }
</style>
